package classifier;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.StringTokenizer;
import java.util.Vector;

import model.BlogPost;

public class LogisticClassifier {
	/*
	 * @param coefficients The coefficients C(i) of the formula. C(0) is the
	 * intercept of the formula.
	 * 
	 * @param factors The values of the factors X(i). Must match the sequence of
	 * the coefficients, with X(0) = 1
	 */
	public double predict(double[] coefficients, double[] factors)
			throws InvalidDataFormatException {
		double prediction = 0.0;
		if (coefficients.length != factors.length) {
			throw new InvalidDataFormatException("Invalid data format:"
					+ "The number of coefficients and factors must match.");
		}
		for (int i = 0; i < coefficients.length; i++) {
			prediction += coefficients[i] * factors[i];
			// System.out.print(coefficients[i] + ":" + factors[i] + " ");
		}
		// System.out.println(" ");
		prediction = (Math.exp(prediction) / (1.0 + Math.exp(prediction)));
		return prediction;
	}

	public double classify(String filename) {
		double accuracy = 0.0;
		double[] coefficients = { 0.19194, 0.01055, -0.01320 };
		HashMap<String, Integer> labels = new HashMap<String, Integer>();
		HashMap<String, Double> predictions = new HashMap<String, Double>();
		FileInputStream fstream;
		try {
			fstream = new FileInputStream(filename);
			BufferedReader in = new BufferedReader(new InputStreamReader(
					fstream));
			String line;
			String blog_id = null;
			int correct = 0, wrong = 0;
			do {
				Vector<Double> factorsVector = new Vector<Double>();
				line = in.readLine();
				if (line != null) {
					StringTokenizer stk = new StringTokenizer(line, ",");
					blog_id = stk.nextToken();
					factorsVector.add(1.0);
					factorsVector.add(Double.parseDouble(stk.nextToken()));
					factorsVector.add(Double.parseDouble(stk.nextToken()));
					labels.put(blog_id, Integer.parseInt(stk.nextToken()));

					double[] factors = new double[factorsVector.size()];
					for (int i = 0; i < factorsVector.size(); i++) {
						factors[i] = factorsVector.get(i);
					}
					// System.out.println(line);
					// System.out.println("Factors:" + factors.length + " "
					// + "Coefficients:" + coefficients.length);
					predictions.put(blog_id, predict(coefficients, factors));
					System.out.println(blog_id + " "
							+ predict(coefficients, factors));
				}
			} while (line != null);

			// Calculate accuracy
			for (String post : labels.keySet()) {
				if (predictions.get(post) < 0.5) {
					if (labels.get(post) == 2) {
						correct++;
					} else {
						wrong++;
					}
				} else {
					if (labels.get(post) == 2) {
						wrong++;
					} else {
						correct++;
					}
				}
			}
			System.out.println(String.format("Accuracy: %.2f", (double) correct
					/ (correct + wrong)));

			fstream.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (InvalidDataFormatException e) {
			e.printStackTrace();
		}
		return accuracy;
	}
}